#include "DeviceInfo.h"
#include "json.h"
#include "log.h"
#include "ConfigApi.h"
#include "mediaPriv.h"
#include "UsbAVStream.h"
#include <iostream>

using namespace ConfigApi;

extern unsigned long long vdo_get_time();

namespace Media{

bool ExternalDevInfo::operator==(const ExternalDevInfo& other) const {
    return m_devModel == other.m_devModel && m_ability == other.m_ability && m_interface == other.m_interface;
}

bool ExternalDevInfo::operator<(const ExternalDevInfo& other) const {
    if (m_devModel != other.m_devModel) {
        return m_devModel < other.m_devModel;
    }
    if (m_interface != other.m_interface) {
        return m_interface < other.m_interface;
    }
    return false;
}


string ExternalDevInfo::getDevModel(){
    return m_devModel;
}

string ExternalDevInfo::getInterface(){
    return m_interface;
}

int ExternalDevInfo::getAbility(){
    return m_ability;
}


/**
 *  获取设备全部信息
*/
bool DeviceInfo::getDevInfo(){
    if(!getDevBaseinfo()){
        LOG_PrintError("getDevBaseinfo error\n");
        return false;
    }

    if(!getDevNetworkinfo()){
        LOG_PrintError("getDevNetworkinfo error\n");
        return false;
    }


    if(!getDevStoreinfo()){
        LOG_PrintError("getDevStoreinfo error\n");
        return false;
    }


    if(!getExterninfo()){
        LOG_PrintError("getExterninfo error\n");
        return false;
    }

    return true;
}

/**
 *  获取设备基本信息
*/
bool DeviceInfo::getDevBaseinfo(){
    //设备类型
    m_devModel = "NearHub_Rooms";
    //设备名称
    Json::Value nameTable;
	string namePath = "DevName";
    IConfigInterface::GetInstance()->Get(namePath, nameTable);
    if(!nameTable.isMember("Name")){
        LOG_PrintError("cannot find devName from config");
        return false;
    }
    m_devName = nameTable["Name"].asString();
    //获取当前设备的RoomId
    Json::Value idTable;
	string roomPath = "Room";
    IConfigInterface::GetInstance()->Get(roomPath, idTable);
    // LOG_PrintError("cannot find wifi from config json ---> %s\n", idTable.toStyledString().c_str());
    if(!idTable.isMember("Id")){
        LOG_PrintError("cannot find RoomId from config");
        return false;
    }
    m_roomId = idTable["Id"].asString();
    //设备sn码
    char snid[64] = {0};
    int status_get_snid = INI_KeyGetString(DEV_HARDWARE_PATH, "hardwareTest", "snid", snid);
    if(status_get_snid < 0){
        LOG_PrintError("openService get snid fail\n");
    }
    m_devSnCode = snid;
    //获取设备当前工作状态
    PlayState state;
    getCurtainPlayState(&state);
    if(state == RUNNING){
        m_workStatus = true;
    }else{
        m_workStatus = false;
    }
    //获取设备当前工作时间
    m_workingTime = vdo_get_time() / 1000;
    //获取设备当前版本号
    FILE * fp;
	char *line = NULL;
	size_t len = 0;
	ssize_t read;
	fp = fopen("/usr/cfg/version_cfg", "r");
	if (fp == NULL)
	{
		return false;
	}
	read = getline(&line, &len, fp);
	if (read <= 0)
	{
		if (line)
		{
			free(line);
		}
		fclose(fp);
		return false;
	}
	m_version = line;
	if (line)
	{
		free(line);
	}
	fclose(fp);
    return true;
}

/**
 * 获取设备网络信息
*/
bool DeviceInfo::getDevNetworkinfo(){
    int ret;
    char netmaskStr[16] = {0};
    char ipaddrStr[16] = {0};
    //获取有线网络信息
    vector<RouteItem> routeTable;
    RouteUtil    routeUtil;
    bool result = routeUtil.GetRouteTabel("eth0", routeTable);
    if(!result)
    {
        LOG_PrintError("GetRouteTabel default failed\n");
        //return false;
    }
    if(routeTable.size() > 0){
        m_wiredGateway = routeTable[0].nexthop;

        if(NetGetHostIPEx("eth0", ipaddrStr,sizeof(ipaddrStr),
                 			netmaskStr, sizeof(netmaskStr))){
            LOG_PrintError("Fail to get ip addr or mask.\n");
            return false;
        }

        m_wiredIP = ipaddrStr;
        m_wiredMask = netmaskStr;
    }
    //获取无线网络信息
    routeTable.clear();
    netmaskStr[16] = {0};
    ipaddrStr[16] = {0};
    routeUtil.GetRouteTabel("wlan0", routeTable);
    if(routeTable.size() > 0){
        m_wirelessGateway = routeTable[0].nexthop;
        if(NetGetHostIPEx("wlan0", ipaddrStr,sizeof(ipaddrStr),
                 			netmaskStr, sizeof(netmaskStr))){
            LOG_PrintError("Fail to get ip addr or mask.\n");
            return false;
        }

        m_wirelessIP = ipaddrStr;
        m_wirelessMask = netmaskStr;
    }
    return true;
}

/**
 * 获取设备存储相关信息
*/
bool DeviceInfo::getDevStoreinfo(){
    //获取设备本身的存储空间信息
    if(!GetSDStorage("/", m_sysTotalSize, m_sysFreeSize)){
        LOG_PrintError("GetSDStorage faild!\n");
        return false;
    }
    //获取SD卡的存储空间信息
    if(isMountPoint("/mnt/sd")){
         if(!GetSDStorage("/mnt/sd", m_sdTotalSize, m_sdFreeSize)){
            LOG_PrintError("GetSDStorage faild!\n");
            return false;
        }
        m_sdTotalSize = m_sdTotalSize/1024;
        m_sdFreeSize = m_sdFreeSize/1024;
    }
    // LOG_PrintWarn("m_sdTotalSize %llu, m_sdFreeSize:%llu\n", m_sdTotalSize, m_sdFreeSize);
    return true;
}


bool DeviceInfo::isMountPoint(const char* directory) {
    struct stat st1, st2;

    // 获取目标目录的 stat 信息
    if (stat(directory, &st1) != 0) {
        // 如果无法获取 stat 信息，可以认为不是独立的挂载点
        return false;
    }

    // 获取目标目录的父目录的 stat 信息
    char parentDirectory[256];
    snprintf(parentDirectory, 256, "%s/..", directory);
    if (stat(parentDirectory, &st2) != 0) {
        // 如果无法获取 stat 信息，可以认为不是独立的挂载点
        return false;
    }

    // 比较两个 stat 信息的设备号是否一致
    return st1.st_dev != st2.st_dev;
}


bool DeviceInfo::GetSDStorage(const char *directory, unsigned long long & total, unsigned long long & free){
    fs::path mountPoint(directory);  // 替换为你的挂载点路径
    fs::space_info space = fs::space(mountPoint);

    // std::cout << "Available space on " << mountPoint << ":" << std::endl;
    // std::cout << "Capacity: " << space.capacity << " bytes" << std::endl;
    // std::cout << "Free: " << space.free << " bytes" << std::endl;
    // std::cout << "Available: " << space.available << " bytes" << std::endl;

    total = space.capacity/(1024*1024);
    free = space.free/(1024*1024);

    return true;
}
/**
 * 获取外部连接设备相关信息
*/
bool DeviceInfo::getExterninfo(){
    set<ExternalDevInfo> externalDevs;
    map<string, int> abilitys;
	map<string, int>::iterator it;
	UsbAVStream::instance()->getAblilityMap(abilitys);
    int ability = 0;   
	for(it = abilitys.begin(); it != abilitys.end(); it++)
	{   
	    string content;
        UsbAVStream::instance()->getDeviceName(it->first, content);
        content =  content;       
		
		int aiblity;
        ability = ((it -> second) & 0xff);  
        LOG_PrintInfo("getUsbAbility::%s ---> %d, Content=%s, ability=%d\n", (it -> first).c_str(), it -> second, content.c_str(), ability);
		switch(ability)
		{
            case 0x01:
                aiblity = VIDEO_ONLY;
                break;
            case 0x02:
            case 0x06:
                aiblity = AUDIO_ONLY;
                break;
            case 0x03:
            case 0x07:
                aiblity = VIDEO_AUDIO;
                break;
            default:
                continue;
		}		
        ExternalDevInfo externInfo(content, ability, it->first); 
        m_externalDev.insert(externInfo);
	}
    return true;
}

bool DeviceInfo::KafkaInfoCompare(DeviceInfo other){
    if(m_devName != other.m_devName){
        return false;
    }
    if(m_devSnCode != other.m_devSnCode){
        return false;
    }
    if(m_workStatus != other.m_workStatus){
        return false;
    }
    if(m_version != other.m_version){
        return false;
    }
    if(m_wiredIP != other.m_wiredIP){
        return false;
    }
    if(m_wirelessIP != other.m_wirelessIP){
        return false;
    }
    if(m_workingTime - other.m_workingTime > 100){
        return false;
    }
    if(m_externalDev != other.m_externalDev){
        return false;
    }
    return true;
}



bool DeviceInfo::getkafkaJson(Json::Value &table){
    table["InternalInfo"]["Name"] = m_devName;
    table["InternalInfo"]["WorkStatus"] = m_workStatus;
    table["InternalInfo"]["Version"] = m_version;
    table["InternalInfo"]["WiredIP"] = m_wiredIP;
    table["InternalInfo"]["WirelessIP"] = m_wirelessIP;
    table["InternalInfo"]["WorkingTime"] = m_workingTime;
    table["InternalInfo"]["SnCode"] = m_devSnCode;
    // 遍历集合并输出元素
    Json::Value jsonArray(Json::arrayValue);
    for (const ExternalDevInfo& dev : m_externalDev) {
        Json::Value externDev;
        externDev["Name"] = dev.getDevModel();
        externDev["DeviceAbility"] = dev.getAbility();
        externDev["ConnectInterface"] = dev.getInterface();
        jsonArray.append(externDev);
    }
    table["ExternalDevInfo"] = jsonArray;
    return true;
}



bool DeviceInfo::httpInfoCompare(DeviceInfo other){
    if(m_devModel != other.m_devModel){
        return false;
    }
    if(m_devName != other.m_devName){
        return false;
    }
    if(m_devSnCode != other.m_devSnCode){
        return false;
    }
    if(m_version != other.m_version){
        return false;
    }
    if(m_roomId != other.m_roomId){
        return false;
    }

    if(m_wiredIP != other.m_wiredIP){
        return false;
    }
    if(m_wiredGateway != other.m_wiredGateway){
        return false;
    }
    if(m_wiredMask != other.m_wiredMask){
        return false;
    }
    if(m_wirelessIP != other.m_wirelessIP){
        return false;
    }
    if(m_wirelessGateway != other.m_wirelessGateway){
        return false;
    }
    if(m_wirelessMask != other.m_wirelessMask){
        return false;
    }

    if(m_sysFreeSize != other.m_sysFreeSize){
        return false;
    }
    if(m_sysTotalSize != other.m_sysTotalSize){
        return false;
    }
    if(m_sdFreeSize != other.m_sdFreeSize){
        return false;
    }
    if(m_sdTotalSize != other.m_sdTotalSize){
        return false;
    }

    if(m_externalDev != other.m_externalDev){
        return false;
    }
    return true;
}

bool DeviceInfo::gethttpJson(Json::Value &table){
    Json::Value jsonArray(Json::arrayValue);
    Json::Value RoomsTable;
    RoomsTable["DevSN"] = m_devSnCode;
    RoomsTable["DeviceNme"] = m_devName;
    RoomsTable["Version"] = m_version;
    RoomsTable["DeviceModel"] = m_devModel;
    RoomsTable["DeviceNme"] = m_devName;
    RoomsTable["RoomId"] = m_roomId;

    Json::Value networkTable(Json::arrayValue);
    if(!m_wiredIP.empty()){
        Json::Value wiredTable;
        wiredTable["Name"] = "eth0";
        wiredTable["Addr"] = m_wiredIP;
        wiredTable["Mask"] = m_wiredMask;
        wiredTable["Gateway"] = m_wiredGateway;
        networkTable.append(wiredTable);
    }
    if(!m_wiredIP.empty()){
        Json::Value wirelessTable;
        wirelessTable["Name"] = "wlan0";
        wirelessTable["Addr"] = m_wirelessIP;
        wirelessTable["Mask"] = m_wirelessMask;
        wirelessTable["Gateway"] = m_wirelessGateway;
        networkTable.append(wirelessTable);
    }
    RoomsTable["Network"] = networkTable;

    Json::Value diskTable(Json::arrayValue);
    if(m_sdTotalSize != 0){
        Json::Value sdTable;
        sdTable["BlockName"] = "/dev/mmcblk2p1";
        sdTable["TotalSize"] = m_sdTotalSize;
        sdTable["AvailableSize"] = m_sdFreeSize;
        diskTable.append(sdTable);
    }
    if(m_sysTotalSize != 0){
        Json::Value sysTable;
        sysTable["BlockName"] = "/dev/mmcblk2";
        sysTable["TotalSize"] = m_sysTotalSize;
        sysTable["AvailableSize"] = m_sysFreeSize;
        diskTable.append(sysTable);       
    }
    RoomsTable["DiskInfo"] = diskTable;
    jsonArray.append(RoomsTable);

     // 遍历集合并输出元素
    for (const ExternalDevInfo& dev : m_externalDev) {
        Json::Value externDev;
        externDev["DeviceNme"] = dev.getDevModel() + "&" + dev.getInterface() + "&" + to_string(dev.getAbility());
        //externDev["DeviceAbility"] = dev.getAbility();
        //externDev["ConnectInterface"] = dev.getInterface();
        externDev["DevSN"] = "";
        externDev["Version"] = "";
        externDev["DeviceModel"] = "";
        externDev["RoomId"] = m_roomId;
        Json::Value emptyArray(Json::arrayValue);
        externDev["Network"] = emptyArray;
        externDev["DiskInfo"] = emptyArray;
        jsonArray.append(externDev);
    }
    table = jsonArray;
    return true;
}


}